package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CategoryClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.*;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.page.QuestionAdminPageQuery;
import com.tianji.learning.domain.page.QuestionPageQuery;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.service.IInteractionReplyService;
import lombok.RequiredArgsConstructor;
import org.aspectj.weaver.ast.Var;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author rui
 * @since 2024-07-21
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {
    private final UserClient userClient;
    private final IInteractionReplyService replyService;
    private final SearchClient searchClient;
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final CategoryClient categoryClient;
    private final CategoryCache categoryCache;
    @Override
    public void saveQuestion(QuestionFormDTO dto) {
        //最终目的是添加一个question数据到表里，由于其他数据都暂时有默认的或者不需要
        //只要保存提问用户id
        Long userId = UserContext.getUser();
        //dto->po
        InteractionQuestion question = BeanUtil.toBean(dto, InteractionQuestion.class);
        question.setUserId(userId);
        save(question);
    }

    @Override
    public void updateQuestion(Long id, QuestionFormDTO dto) {
        //1.首先判断参数是否正常
        if(dto.getTitle() == null || dto.getAnonymity() == null ||
                dto.getDescription() == null){
            throw new BadRequestException("请求参数不正常");
        }
        //2.通过请求的id来查询数据是否存在
        InteractionQuestion question = getById(id);
        if(question == null){
            throw new DbException("互动问题数据不存在");
        }
        //3.修改对应的参数
        question.setUserId(UserContext.getUser());
        question.setAnonymity(dto.getAnonymity());
        question.setDescription(dto.getDescription());
        question.setTitle(dto.getTitle());
        boolean success = updateById(question);
        if(!success){
            throw new DbException("修改失败");
        }
    }

    @Override
    public PageDTO<QuestionVO> queryQuestions(QuestionPageQuery pageQuery) {
        //1.初始化返回的参数
        PageDTO<QuestionVO> pageDTO = new PageDTO<>();
        // 1.参数校验，课程id和小节id不能都为空
        Long courseId = pageQuery.getCourseId();
        Long sectionId = pageQuery.getSectionId();
        if (courseId == null && sectionId == null) {
            throw new BadRequestException("课程id和小节id不能都为空");
        }
        // 2.分页查询
        Page<InteractionQuestion> page = lambdaQuery()
                .select(InteractionQuestion.class, info -> !info.getProperty().equals("description"))
                .eq(pageQuery.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(courseId != null, InteractionQuestion::getCourseId, courseId)
                .eq(sectionId != null, InteractionQuestion::getSectionId, sectionId)
                .eq(InteractionQuestion::getHidden, false)
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());

        //3.获取问题列表
        List<InteractionQuestion> questions = page.getRecords();

        //3.1 将最近回答的用户id和提问问题的用户id都放在一起，便于查询
        Set<Long> userIds = new HashSet<>();
        //回答的表主键
        Set<Long> answerIds = new HashSet<>();
        for (InteractionQuestion question : questions) {
            if(!question.getAnonymity()){
                //提问的用户不匿名
                userIds.add(question.getUserId());
            }
            if(question.getLatestAnswerId()!=null){
                //可能第一次提问，没有用户回答
                answerIds.add(question.getLatestAnswerId());
            }
        }
        Map<Long,InteractionReply> replyMap = new HashMap<>();
        //3.2 根据answerId查询reply表信息
        if(CollUtil.isNotEmpty(answerIds)){
            List<InteractionReply> interactionReplies = replyService.lambdaQuery()
                    .eq(InteractionReply::getHidden, false)
                    .in(InteractionReply::getId, answerIds).list();

            if (CollUtils.isNotEmpty(interactionReplies)){
                for (InteractionReply reply : interactionReplies) {
                    if(!reply.getAnonymity()){
                        //回答的人不匿名
                        userIds.add(reply.getUserId());
                    }
                    replyMap.put(reply.getId(),reply);
                }
            }
        }

        //3.3 远程调用user获取用户昵称，头像
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userDTOMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));

        //4.封装返回结果
        pageDTO.setTotal(page.getTotal());
        pageDTO.setPages(page.getPages());
        List<QuestionVO> questionVOS = new ArrayList<>();
        for (InteractionQuestion question : questions) {
            QuestionVO questionVO = BeanUtil.toBean(question, QuestionVO.class);
            if(!questionVO.getAnonymity()){
                UserDTO userDTO = userDTOMap.get(questionVO.getUserId());
                if(userDTO!=null){
                    questionVO.setUserName(userDTO.getName());
                    questionVO.setUserIcon(userDTO.getIcon());
                }
            }
            InteractionReply interactionReply = replyMap.get(questionVO.getId());
            if(interactionReply != null){
                if(!interactionReply.getAnonymity()){
                    UserDTO userDTO = userDTOMap.get(interactionReply.getUserId());
                    if(userDTO!=null){
                        questionVO.setUserName(userDTO.getName());
                    }
                }
                questionVO.setLatestReplyContent(interactionReply.getContent());
            }
            questionVOS.add(questionVO);
        }
        pageDTO.setList(questionVOS);
        return pageDTO;
    }

    @Override
    public QuestionVO queryByQuestionId(Long id) {
        //1.根据id查询对于的问题是否存在
        InteractionQuestion question = lambdaQuery()
                .eq(InteractionQuestion::getId,id)
                .one();
        if(question == null){
            throw new BadRequestException("查询的问题不存在");
        }
        if(question.getHidden()){
            //管理员设置隐藏
            return null;
        }
        //2.封装返回对象
        QuestionVO questionVO = BeanUtil.toBean(question, QuestionVO.class);
        if(!question.getAnonymity()){
            UserDTO userDTO = userClient.queryUserById(question.getUserId());
            if(userDTO == null){
                throw new DbException("用户信息不存在");
            }
            //2.1 封装非匿名用户信息
            questionVO.setUserName(userDTO.getName());
            questionVO.setUserIcon(userDTO.getIcon());
        }

        return questionVO;
    }

    @Override
    public void deleteQuestionById(Long id) {
        if(id == null){
            throw new BadRequestException("id参数不合法");
        }
        Long userId = UserContext.getUser();
        //判断是否是本人删除
        boolean success = remove(new LambdaQueryWrapper<InteractionQuestion>()
                .eq(InteractionQuestion::getUserId,userId)
                .eq(InteractionQuestion::getId,id));
        if(!success){
            throw new DbException("删除问题不成功");
        }
        replyService.remove(new LambdaQueryWrapper<InteractionReply>()
                .eq(InteractionReply::getQuestionId,id));
    }

    @Override
    public PageDTO<QuestionAdminVO> adminPageQuery(QuestionAdminPageQuery pageQuery) {
        //1.先通过es查看课程名称转id
        List<Long> cids = null;
        if(StrUtil.isNotBlank(pageQuery.getCourseName())){
            cids = searchClient.queryCoursesIdByName(pageQuery.getCourseName());
            if(CollUtil.isEmpty(cids)){
                //如果集合为空则直接返回null
                return PageDTO.empty(0L,0L);
            }
        }

        //2.通过传递的条件判断是否查询该参数
        Page<InteractionQuestion> page = lambdaQuery()
                .in(cids!=null,InteractionQuestion::getCourseId, cids)
                .eq(pageQuery.getStatus() != null, InteractionQuestion::getStatus, pageQuery.getStatus())
                .ge(pageQuery.getBeginTime() != null, InteractionQuestion::getCreateTime, pageQuery.getBeginTime())
                .le(pageQuery.getEndTime() != null, InteractionQuestion::getCreateTime, pageQuery.getEndTime())
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> questions = page.getRecords();
        if(CollUtil.isEmpty(questions)){
            return PageDTO.empty(0L,0L);
        }

        //3.远程调用用户服务获得用户昵称
        List<Long> uids = questions.stream().map(InteractionQuestion::getUserId).collect(Collectors.toList());
        List<UserDTO> userDTOS = userClient.queryUserByIds(uids);
        Map<Long, UserDTO> userDTOMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));

        //4.远程调用服务获得课程名称 分类名称 章节名称 小节名称
        Set<Long> chapterAndSectionIds = new HashSet<>();
        Set<Long> courseIds = new HashSet<>();
        for (InteractionQuestion question : questions) {
            if(question != null){
                chapterAndSectionIds.add(question.getChapterId());
                chapterAndSectionIds.add(question.getSectionId());
                courseIds.add(question.getCourseId());
            }
        }

        //4.1 课程名称
        List<CourseSimpleInfoDTO> simpleInfoList = courseClient.getSimpleInfoList(courseIds);
        if(CollUtil.isEmpty(simpleInfoList)){
            throw new DbException("课程不存在");
        }
        Map<Long, CourseSimpleInfoDTO> courseMap = simpleInfoList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));

        //4.2 章节名称 小节名称
        List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(chapterAndSectionIds);
        if(CollUtil.isEmpty(cataSimpleInfoDTOS)){
            throw new BizIllegalException("章节信息不存在");
        }
        Map<Long, CataSimpleInfoDTO> cataSimpleInfoDTOMap = cataSimpleInfoDTOS.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, c -> c));

        //4.3分类名称

        //5.封装结果返回
        List<QuestionAdminVO> voList = new ArrayList<>();
        for (InteractionQuestion question : questions) {
            QuestionAdminVO questionAdminVO = BeanUtil.toBean(question, QuestionAdminVO.class);
            if(question.getUserId() != null){
                UserDTO userDTO = userDTOMap.get(question.getUserId());
                if(userDTO!=null)
                questionAdminVO.setUserName(userDTO.getName());
            }
            if(question.getCourseId()!=null){
                String categoryNames = categoryCache.getCategoryNames(courseMap.get(question.getCourseId()).getCategoryIds());
                questionAdminVO.setCategoryName(categoryNames);
                questionAdminVO.setCourseName(courseMap.get(question.getCourseId()).getName());
            }
            String chapterName = cataSimpleInfoDTOMap.get(question.getChapterId()).getName();
            questionAdminVO.setChapterName(chapterName==null?"": chapterName);
            String sectionName = cataSimpleInfoDTOMap.get(question.getSectionId()).getName();
            questionAdminVO.setSectionName(sectionName==null?"": sectionName);
            voList.add(questionAdminVO);
        }
        PageDTO<QuestionAdminVO> pageDTO = new PageDTO<>();
        pageDTO.setPages(page.getPages());
        pageDTO.setTotal(page.getTotal());
        pageDTO.setList(voList);
        return pageDTO;
    }

    @Override
    public void updateHiddenById(Long questionId, Boolean hidden) {
        if(questionId == null || hidden == null){
            throw new BadRequestException("请求参数不正常");
        }
        //1.利用问题id查询是否有该问题
        InteractionQuestion question = getById(questionId);
        if(question == null){
            return;
        }
        //2.不为空则更新字段
        question.setHidden(hidden);
        boolean success = updateById(question);
        if(!success){
            throw new DbException("设置隐藏状态失败");
        }
    }

    @Override
    public QuestionAdminVO adminQueryByQuestionId(Long questionId) {
        if(questionId == null){
            return null;
        }
        //1.利用问题id查询是否有该问题
        InteractionQuestion question = getById(questionId);
        if(question == null){
            throw new BizIllegalException("问题不存在");
        }

        //2. 封装返回对象
        QuestionAdminVO questionAdminVO = BeanUtil.toBean(question, QuestionAdminVO.class);
        //2.1 封装用户昵称
        UserDTO userDTO = userClient.queryUserById(question.getUserId());
        if(userDTO != null){
            questionAdminVO.setUserName(userDTO.getName());
            questionAdminVO.setUserIcon(userDTO.getIcon());
        }
        //2.2 课程三级分类 课程名称  课程所属章节
        CourseFullInfoDTO courseInfoById = courseClient.getCourseInfoById(question.getCourseId(), true, true);
        List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(List.of(question.getChapterId(), question.getSectionId()));
        if(courseInfoById != null){
            questionAdminVO.setCourseName(courseInfoById.getName());
            //课程三级分类
            String categoryNames = categoryCache.getCategoryNames(courseInfoById.getCategoryIds());
            questionAdminVO.setCategoryName(categoryNames);
            //课程老师名称
            List<UserDTO> userDTOS = userClient.queryUserByIds(courseInfoById.getTeacherIds());
            if(CollUtil.isNotEmpty(userDTOS)){
                questionAdminVO.setTeacherName(userDTOS.stream()
                        .map(UserDTO::getName).collect(Collectors.joining("/")));
            }
        }
        //课程所属章节
        Map<Long, CataSimpleInfoDTO> cataSimpleInfoDTOMap = cataSimpleInfoDTOS.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, c -> c));
        if(CollUtil.isNotEmpty(cataSimpleInfoDTOMap)){
            CataSimpleInfoDTO chapterName = cataSimpleInfoDTOMap.get(question.getChapterId());
            CataSimpleInfoDTO sectionName = cataSimpleInfoDTOMap.get(question.getSectionId());
            if(chapterName!=null && sectionName != null){
                questionAdminVO.setSectionName(sectionName.getName());
                questionAdminVO.setChapterName(chapterName.getName());
            }
        }

        return questionAdminVO;
    }

}
